#if !defined(PIECE_H)
#define PIECE_H
#include <stdio.h>
#include <set>
#include "ChessGuiDefines.h"
#include "Cell.h"

///@brief Virtual base class for all %Piece objects
class Piece {

	public:

		~Piece(){
			validMoves->clear();
			delete(validMoves);
			this->cell = NULL;
		}
		void BindToCell(Cell* cell) {
			this->cell = cell;
		}			

		Cell* GetCell() {
			return cell;
		}
		PieceType GetType() {
			return type;
		}
		PieceColor GetColor() {
			return color;
		}
		ImageName GetImageName() {
			return imageName;
		}
		int GetId() {
			return id;
		}
		int GetRow() {
			if (cell == NULL)
				return -1;
			else
				return cell->GetRow();
		}
		int GetCol() {
			if (cell == NULL)
				return -1;
			else
				return cell->GetCol();
		}

		virtual std::set<Cell*>* GetValidMoves() = 0;
		virtual bool ValidMovesContains(Cell* cell) = 0;
		
		std::string getTypeString(){
			std::string typeString = "" ;
			switch(this->type)
			{
			case ROOK: typeString = "ROOK"; break;
			case KING: typeString = "KING"; break;
			case QUEEN: typeString = "QUEEN"; break;
			case KNIGHT: typeString = "KNIGHT"; break;
			case BISHOP: typeString = "BISHOP"; break;
			case PAWN: typeString = "PAWN"; break;
			}
			return typeString;
		}
		std::string getColorString(){
			std::string typeString = "" ;
			switch(this->color)
			{
			case BLACK: typeString = "BLACK"; break;
			case WHITE: typeString = "WHITE"; break;
			}
			return typeString;
		}
		std::string toXmlString(){
			std::string output = "<piece ";
			char col[21]; // enough to hold all numbers up to 64-bits
			sprintf(col, "%d", this->GetCol());
			char row[21]; // enough to hold all numbers up to 64-bits
			sprintf(row, "%d", this->GetRow());




			output += "type =\""+this->getTypeString();
			output += "\" color =\""+this->getColorString();
			output += "\" row =\"";
			output += row;
			output += "\" column =\"";
			output += col;
			output += "\" />";
			return output;
		}
		std::string toXmlString(Cell * fromcell){
			std::string output = "<piece ";
			char col[21]; // enough to hold all numbers up to 64-bits
			sprintf(col, "%d", fromcell->GetCol());
			char row[21]; // enough to hold all numbers up to 64-bits
			sprintf(row, "%d", fromcell->GetRow());

			output += "type=\""+this->getTypeString();
			output += "\" color=\""+this->getColorString();
			output += "\" row=\"";
			output += row;
			output += "\" column=\"";
			output += col;
			output += "\" />";
			return output;
		}

	protected:
		PieceType type;
		PieceColor color;
		ImageName imageName;
		int id;
		
		/// A pointer to the cell this piece is bound to (already exists on heap). 
		Cell* cell;
		
		/// A pointer to a set (allocated by this class) containing the 
		/// cells this piece can move to.  
		///@note This set should never contain the cell this piece is bound to. 
		///@note This set should always be updated when it is called by
		/// GetValidMoves() or ValidMovesContains()
		std::set<Cell*>* validMoves;
		
		/// Update validMoves to match the state of the current board. 
		virtual void UpdateValidMoves() = 0;
};

#endif
